﻿using LightCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.Core.Element3d
{
    public class LoftAttribute : CptAttribute
    {
        public LoftAttribute(string category, string subCategorys) : base(category, subCategorys)
        {
        }
        public override LcComponentDefinition GetBuiltinCpt(string subCategory)
        {
            return null;
        }
    }


    [LoftAttribute("放样体", "放样体")]
    public class LcLoftDef : LcComponentDefinition
    {
        static LcLoftDef()
        {
            CptTypeParamsDef<LcLoftDef>.ParamsDef = new ParameterSetDefinition {
                new ParameterDefinition { DataType = LcDataType.String, Name = "MaterialId", DisplayName = "材质", },
                new ParameterDefinition { DataType = LcDataType.String, Name = "SectionId", DisplayName = "截面", }
            };
        }
        public LcLoftDef()
        {
            this.TypeParameters = new LcParameterSet(CptTypeParamsDef<LcLoftDef>.ParamsDef);
        }
        public LcLoftDef(string uuid, string name, string sectionId) : base(uuid, name, "放样体", "放样体", new LcParameterSet(CptTypeParamsDef<LcLoftDef>.ParamsDef))
        {
            this.TypeParameters.SetValue("SectionId", sectionId);
            this.Parameters = new ParameterSetDefinition
                {
                    new ParameterDefinition { Name = "Path", DataType = LcDataType.CurveArray } ,
                };

            this.Curve2dProvider = new Curve2dProvider("放样体")
            {
                GetCurve2dsFunc = (p) =>
                {
                    var path = p.GetValue<List<Curve2d>>("Path");
                    //var box = new Box2(new Vector2(-size, -size), new Vector2(size, size));
                    return null; ;
                }
            };
            this.Solid3dProvider = new Solid3dProvider("放样体")
            {
                GetSolid3dsFunc = (p) =>
                {
                    var path2d = p.GetValue<List<Curve2d>>("Path");
                    var sectionIds = this.TypeParameters.GetValue<string>("SectionId").Split(',');
                    PlanarSurface3d profile;
                    var solids = new Solid3dCollection();
                    foreach (var sectionId in sectionIds)
                    {
                        if (SectionManager.Sections.TryGetValue(sectionId, out var section))
                        {
                            var curve3ds = section.Segments.Select(n =>
                            {
                                Curve3d curve = n.ToCurve3d();
                                curve.RotateRoundAxis(Vector3.Origin, Vector3.XAxis, Math.PI / 2);
                                return curve;
                            }).ToList();
                            var inCurve3ds = section.InnerSegments.Select(m => m.Select(n =>
                            {
                                Curve3d curve = n.ToCurve3d();
                                curve.RotateRoundAxis(Vector3.Origin, Vector3.XAxis, Math.PI / 2);
                                return curve;
                            }).ToList());
                            var path3d = new List<Curve3d>();
                            for (int i = 0; i < path2d.Count; i++)
                            {
                                path3d.Add(path2d[i].ToCurve3d());
                            }
                            profile = new PlanarSurface3d(new Plane(new Vector3(0, 1, 0)), curve3ds);
                            profile.InnerLoops.AddRange(inCurve3ds);
                            solids.Add(new Loft3d(profile, path3d, new Vector3()));
                        }
                    }
                    return solids;
                }
            };
        }
    }

    public class LcLoftInstance : LcComponentInstance
    {
        public LcLoftInstance(LcLoftDef lcLoft) : base(lcLoft)
        {
            this.Type = BuiltinElementType.Loft;
        }
        public LcLoftInstance(List<Curve2d> path, LcLoftDef lcLoft) : base(lcLoft)
        {
            this.Type = BuiltinElementType.Loft;
            this.Parameters.SetValue("Path", path);
        }
        public override LcElement Clone()
        {
            var loft = new LcLoftInstance(this.Definition as LcLoftDef);
            loft.Initilize(this.Document);
            loft.Copy(this);
            return loft;
        }
    }
}